package com.bioscript.standalone.dataStructures;

import java.util.ArrayList;
import java.util.List;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

public class Contig {
	
	private transient Range actualRange, mappedRange;
	private transient int reads, cgs;
	private transient float coverage;
	private transient List<Gene> genes ;
	private transient List<Snp> snps ;
	
	public static Contig getInstance(String str)
	{
		String[] params = str.split(" ");
		Range mappedRange = new Range(Integer.parseInt(params[1].split("\\.\\.")[0]), 
				Integer.parseInt(params[1].split("\\.\\.")[1]));
		return new Contig(mappedRange, Integer.parseInt(params[2].split("=")[1]), params[0].substring(1)).
		setCgs(Integer.parseInt(params[6].split("=")[1])).
		setReads(params[3].split("=")[1].equals("-") ? 0 : Integer.parseInt(params[3].split("=")[1])).
		setCoverage(params[4].split("=")[1].equals("-") ? 0 : Float.parseFloat(params[4].split("=")[1]));
	}
	
	public Contig(Range mappedRange, int length , String name)
	{
		this.actualRange = new Range(1, length,name);
		this.mappedRange = new Range
		(mappedRange.getLowerLimit(), mappedRange.getUpperLimit(), 
				mappedRange.getName()).setMetadata(mappedRange.getMetadata());
	}
	
	public Contig setMetaData(String metadata)
	{
		actualRange.setMetadata(metadata);
		return this;
	}
	
//	public Range getMapping()
//	{
//		return new Range(mappedRange.getLowerLimit(),mappedRange.getUpperLimit(),mappedRange.getName())
//		.setMetadata(mappedRange.getMetadata());
//	}
	
//	public Range getContig()
//	{
//		return new Range(actualRange.getLowerLimit(),actualRange.getUpperLimit(),actualRange.getName())
//		.setMetadata(actualRange.getMetadata());
//	}
	
	public Range getContig() {
		return actualRange;
	}

	public Range  getMapping() {
		return mappedRange;
	}

	public void setActualRange(Range actualRange) {
		this.actualRange = actualRange;
	}

	public void setMappedRange(Range mappedRange) {
		this.mappedRange = mappedRange;
	}

	public int getReads()
	{
		return this.reads;
	}
	
	public float getCoverage()
	{
		return this.coverage;
	}
	
	public int getCgs()
	{
		return this.cgs;
	}

	public Contig addSnp(Snp snp)
	{
		if (snps == null)
		{
			snps = new ArrayList<Snp>();
		}
		
		Snp newSnp = new Snp(snp.getRange());
		snps.add(newSnp);
		return this;
	}
	
	public Contig addGenes(Gene gene)
	{
		if (genes == null)
		{
			genes = new ArrayList<Gene>();
		}
		
		Gene newGene = new Gene(gene.getGene()).setExpectedPosition(gene.getExpectedPosition());
		genes.add(newGene);
		return this;
	}
	
	public List<Snp> getSnps()
	{
		return new ArrayList<Snp>(this.snps);
	}
	
	public List<Gene> getGenes()
	{
		return new ArrayList<Gene>(this.genes);
	}
	
	public Contig setReads(int reads) {
		this.reads = reads;
		return this;
	}
	
	public Contig setCoverage(float coverage) {
		this.coverage = coverage;
		return this;
	}
	
	public Contig setCgs(int cgs) {
		this.cgs = cgs;
		return this;
	}
	
	public String convertToString()
	{
		return actualRange.getName() + "\t" + mappedRange.getLowerLimit() + "\t" +
				mappedRange.getUpperLimit() + "\t" + actualRange.getLength() + "\t" +
				reads + "\t" + coverage + "\t" + cgs;
	}
	
	public Element toXML(Document doc)
	{
		try
		{
			Element con = doc.createElement("contig");
			if (mappedRange != null)
			{
				con.setAttribute("refStart", String.valueOf(mappedRange.getLowerLimit()));
				con.setAttribute("refEnd", String.valueOf(mappedRange.getUpperLimit()));
			}
			con.setAttribute("name", actualRange.getName());
			con.setAttribute("length", String.valueOf(actualRange.getLength()));
			con.setAttribute("meta", actualRange.getMetadata() == null ? "" : actualRange.getMetadata());
			con.setAttribute("reads", String.valueOf(reads));
			con.setAttribute("cgContent", String.valueOf(cgs));
			
			Element snpList = doc.createElement("snpList");
			snpList.setAttribute("size", snps == null ? "0" : String.valueOf(snps.size()));
			if (snps != null)
			{
				for (Snp snp : snps)
				{
					Element sn = snp.toXML(doc);
					snpList.appendChild(sn);
				}
			}
			con.appendChild(snpList);
			
			Element geneList = doc.createElement("geneList");
			geneList.setAttribute("size", genes == null ? "0" : String.valueOf(genes.size()));
			if (genes != null)
			{
				for (Gene gene : genes)
				{
					Element g = gene.toXML(doc);
					geneList.appendChild(g);
				}
			}
			con.appendChild(geneList);
			return con;
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		return null;
	}
	
	public static List<String> getList(List<Contig> lst)
	{
		List<String> strs = new ArrayList<String>();
		for(Contig contig : lst)
		{
			strs.add(contig.convertToString());
		}
		return strs;
	}
}
